"""
观察者模式实现
实现事件驱动架构,用于处理用户注册、内容发布、互动等事件
"""
from abc import ABC, abstractmethod
from typing import Dict, Any, List, Callable, Optional
from enum import Enum
from datetime import datetime
import logging

logger = logging.getLogger(__name__)


class EventType(Enum):
    """事件类型枚举"""
    USER_REGISTERED = "user_registered"          # 用户注册
    USER_LOGIN = "user_login"                    # 用户登录
    CONTENT_PUBLISHED = "content_published"      # 内容发布
    CONTENT_LIKED = "content_liked"              # 内容点赞
    CONTENT_COLLECTED = "content_collected"      # 内容收藏
    CONTENT_COMMENTED = "content_commented"      # 内容评论
    USER_FOLLOWED = "user_followed"              # 用户关注
    IDENTITY_VERIFIED = "identity_verified"      # 实名认证通过


class Event:
    """事件对象"""
    
    def __init__(self, event_type: EventType, data: Dict[str, Any], 
                 user_id: Optional[int] = None):
        self.event_type = event_type
        self.data = data
        self.user_id = user_id
        self.timestamp = datetime.now()
        
    def __repr__(self):
        return f"Event({self.event_type.value}, user_id={self.user_id}, timestamp={self.timestamp})"


class EventListener(ABC):
    """事件监听器基类"""
    
    @abstractmethod
    def handle(self, event: Event):
        """
        处理事件
        
        Args:
            event: 事件对象
        """
        pass
    
    @abstractmethod
    def get_listener_name(self) -> str:
        """获取监听器名称"""
        pass
    
    def can_handle(self, event: Event) -> bool:
        """
        判断是否能处理该事件
        子类可以重写此方法进行更细粒度的控制
        """
        return True


class EventManager:
    """
    事件管理器 - 观察者模式的核心
    负责注册监听器和分发事件
    """
    
    _instance = None
    
    def __new__(cls):
        """单例模式确保只有一个事件管理器"""
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance._listeners = {}
        return cls._instance
    
    def subscribe(self, event_type: EventType, listener: EventListener):
        """
        订阅事件
        
        Args:
            event_type: 事件类型
            listener: 事件监听器
        """
        if event_type not in self._listeners:
            self._listeners[event_type] = []
        
        if listener not in self._listeners[event_type]:
            self._listeners[event_type].append(listener)
            logger.info(f"监听器 {listener.get_listener_name()} 订阅了事件 {event_type.value}")
    
    def unsubscribe(self, event_type: EventType, listener: EventListener):
        """
        取消订阅事件
        
        Args:
            event_type: 事件类型
            listener: 事件监听器
        """
        if event_type in self._listeners:
            if listener in self._listeners[event_type]:
                self._listeners[event_type].remove(listener)
                logger.info(f"监听器 {listener.get_listener_name()} 取消订阅了事件 {event_type.value}")
    
    def publish(self, event: Event):
        """
        发布事件
        
        Args:
            event: 事件对象
        """
        logger.info(f"发布事件: {event}")
        
        listeners = self._listeners.get(event.event_type, [])
        
        for listener in listeners:
            try:
                if listener.can_handle(event):
                    listener.handle(event)
                    logger.info(f"监听器 {listener.get_listener_name()} 成功处理事件 {event.event_type.value}")
            except Exception as e:
                logger.error(f"监听器 {listener.get_listener_name()} 处理事件失败: {e}")
                import traceback
                traceback.print_exc()
    
    def clear(self):
        """清除所有监听器"""
        self._listeners.clear()
        logger.info("已清除所有事件监听器")
    
    def get_listeners(self, event_type: EventType = None) -> Dict[EventType, List[EventListener]]:
        """
        获取监听器列表
        
        Args:
            event_type: 事件类型，如果为None则返回所有监听器
        """
        if event_type:
            return {event_type: self._listeners.get(event_type, [])}
        return self._listeners.copy()


# ==================== 具体的事件监听器实现 ====================

class WelcomeMessageListener(EventListener):
    """欢迎消息监听器 - 用户注册后发送欢迎消息"""
    
    def handle(self, event: Event):
        """处理用户注册事件"""
        user = event.data.get('user')
        if user:
            logger.info(f"发送欢迎消息给用户: {user.username} (ID: {user.id})")
            # 这里可以集成消息推送服务
            # 例如: send_welcome_notification(user)
    
    def get_listener_name(self) -> str:
        return "WelcomeMessageListener"


class InitUserInterestsListener(EventListener):
    """初始化用户兴趣监听器 - 用户注册后初始化兴趣标签"""
    
    def handle(self, event: Event):
        """处理用户注册事件"""
        user = event.data.get('user')
        db = event.data.get('db')
        
        if user and db:
            logger.info(f"初始化用户兴趣标签: {user.username} (ID: {user.id})")
            # 这里可以调用初始化兴趣标签的服务
            # 例如: init_user_interests(db, user.id)
    
    def get_listener_name(self) -> str:
        return "InitUserInterestsListener"


class UpdateESIndexListener(EventListener):
    """更新ES索引监听器 - 内容发布后更新搜索索引"""
    
    def handle(self, event: Event):
        """处理内容发布事件"""
        content = event.data.get('content')
        
        if content:
            logger.info(f"更新ES索引: 内容ID {content.id}")
            # 这里可以调用ES更新服务
            # 例如: update_es_index(content)
    
    def get_listener_name(self) -> str:
        return "UpdateESIndexListener"


class NotifyFollowersListener(EventListener):
    """通知粉丝监听器 - 内容发布后通知粉丝"""
    
    def handle(self, event: Event):
        """处理内容发布事件"""
        content = event.data.get('content')
        db = event.data.get('db')
        
        if content and db:
            logger.info(f"通知粉丝: 用户 {content.user_id} 发布了新内容 {content.id}")
            # 这里可以查询粉丝列表并发送通知
            # 例如: notify_followers(db, content)
    
    def get_listener_name(self) -> str:
        return "NotifyFollowersListener"


class ContentStatisticsListener(EventListener):
    """内容统计监听器 - 处理点赞、收藏、评论等互动"""
    
    def handle(self, event: Event):
        """处理互动事件"""
        content_id = event.data.get('content_id')
        user_id = event.data.get('user_id')
        db = event.data.get('db')
        
        if content_id and db:
            logger.info(f"更新内容统计: 内容ID {content_id}, 事件类型 {event.event_type.value}")
            # 这里可以更新内容的统计数据
            # 例如: update_content_stats(db, content_id, event.event_type)
    
    def get_listener_name(self) -> str:
        return "ContentStatisticsListener"


class NotifyAuthorListener(EventListener):
    """通知作者监听器 - 互动后通知内容作者"""
    
    def handle(self, event: Event):
        """处理互动事件"""
        content_id = event.data.get('content_id')
        user_id = event.data.get('user_id')
        db = event.data.get('db')
        
        if content_id and user_id and db:
            logger.info(f"通知内容作者: 内容ID {content_id} 收到了 {event.event_type.value}")
            # 这里可以发送通知给作者
            # 例如: notify_content_author(db, content_id, user_id, event.event_type)
    
    def get_listener_name(self) -> str:
        return "NotifyAuthorListener"


class UpdateUserInterestListener(EventListener):
    """更新用户兴趣监听器 - 根据互动更新用户兴趣模型"""
    
    def handle(self, event: Event):
        """处理互动事件"""
        user_id = event.data.get('user_id')
        content_id = event.data.get('content_id')
        db = event.data.get('db')
        
        if user_id and content_id and db:
            logger.info(f"更新用户兴趣模型: 用户ID {user_id}, 内容ID {content_id}")
            # 这里可以更新用户的兴趣向量
            # 例如: update_user_interest_vector(db, user_id, content_id, event.event_type)
    
    def get_listener_name(self) -> str:
        return "UpdateUserInterestListener"


class UserLoginLogListener(EventListener):
    """用户登录日志监听器 - 记录用户登录行为"""
    
    def handle(self, event: Event):
        """处理用户登录事件"""
        user = event.data.get('user')
        login_method = event.data.get('login_method', 'unknown')
        
        if user:
            logger.info(f"用户登录: {user.username} (ID: {user.id}), 登录方式: {login_method}")
            # 这里可以记录登录日志
            # 例如: log_user_login(user, login_method)
    
    def get_listener_name(self) -> str:
        return "UserLoginLogListener"


class IdentityVerificationListener(EventListener):
    """实名认证监听器 - 处理实名认证通过事件"""
    
    def handle(self, event: Event):
        """处理实名认证通过事件"""
        user = event.data.get('user')
        verification = event.data.get('verification')
        
        if user and verification:
            logger.info(f"用户实名认证通过: {user.username} (ID: {user.id}), 姓名: {verification.real_name}")
            # 这里可以发送认证通过通知，解锁更多功能
            # 例如: unlock_verified_features(user)
    
    def get_listener_name(self) -> str:
        return "IdentityVerificationListener"


def init_default_listeners():
    """初始化默认的事件监听器"""
    event_manager = EventManager()
    
    # 用户注册事件监听器
    event_manager.subscribe(EventType.USER_REGISTERED, WelcomeMessageListener())
    event_manager.subscribe(EventType.USER_REGISTERED, InitUserInterestsListener())
    
    # 内容发布事件监听器
    event_manager.subscribe(EventType.CONTENT_PUBLISHED, UpdateESIndexListener())
    event_manager.subscribe(EventType.CONTENT_PUBLISHED, NotifyFollowersListener())
    
    # 互动事件监听器
    event_manager.subscribe(EventType.CONTENT_LIKED, ContentStatisticsListener())
    event_manager.subscribe(EventType.CONTENT_LIKED, NotifyAuthorListener())
    event_manager.subscribe(EventType.CONTENT_LIKED, UpdateUserInterestListener())
    
    event_manager.subscribe(EventType.CONTENT_COLLECTED, ContentStatisticsListener())
    event_manager.subscribe(EventType.CONTENT_COLLECTED, NotifyAuthorListener())
    event_manager.subscribe(EventType.CONTENT_COLLECTED, UpdateUserInterestListener())
    
    event_manager.subscribe(EventType.CONTENT_COMMENTED, ContentStatisticsListener())
    event_manager.subscribe(EventType.CONTENT_COMMENTED, NotifyAuthorListener())
    event_manager.subscribe(EventType.CONTENT_COMMENTED, UpdateUserInterestListener())
    
    # 用户登录事件监听器
    event_manager.subscribe(EventType.USER_LOGIN, UserLoginLogListener())
    
    # 实名认证事件监听器
    event_manager.subscribe(EventType.IDENTITY_VERIFIED, IdentityVerificationListener())
    
    logger.info("已初始化所有默认事件监听器")
    return event_manager

